package cn.com.utt.unms.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;

import cn.com.utt.common.log.doLog;
import cn.com.utt.common.util.LocaleMessageSourceUtil;
import cn.com.utt.common.util.Tips;
import cn.com.utt.common.vo.RestResult;
import cn.com.utt.common.vo.SearchParameter;
import cn.com.utt.common.vo.TableInput;
import cn.com.utt.common.vo.TableOutput;
import cn.com.utt.unms.mapper.DeviceMapper;
import cn.com.utt.unms.mapper.GroupMapper;
import cn.com.utt.unms.mapper.LocationMapper;
import cn.com.utt.unms.mapper.NetworkMapper;
import cn.com.utt.unms.mapper.SsidMapper;
import cn.com.utt.unms.mapper.GroupNetworkMapper;
import cn.com.utt.unms.mapper.WirelessMapper;
import cn.com.utt.unms.mapper.WirelessNetworkMapper;
import cn.com.utt.unms.pojo.Device;
import cn.com.utt.unms.pojo.Group;
import cn.com.utt.unms.pojo.Location;
import cn.com.utt.unms.pojo.Network;
import cn.com.utt.unms.pojo.Wireless;
import cn.com.utt.unms.service.DeviceService;
import cn.com.utt.unms.service.GroupService;
import cn.com.utt.unms.service.NetworkService;
import cn.com.utt.unms.vo.NetworkInfo;
import cn.com.utt.unms.vo.NetworkInput;

@Service("networkService")
public class NetworkServiceImpl implements NetworkService {
	
	@Autowired
    private LocaleMessageSourceUtil messageSourceUtil;

	@Autowired
	private NetworkMapper networkMapper;

	@Autowired
	private GroupMapper groupMapper;

	@Autowired
	private GroupNetworkMapper groupNetworkMapper;

	@Autowired
	private WirelessNetworkMapper wirelessNetworkMapper;

	@Autowired
	private SsidMapper ssidMapper;

	@Autowired
	private DeviceMapper deviceMapper;

	@Autowired
	private DeviceService deviceService;
	
	@Autowired
	private LocationMapper locationMapper;

	@Autowired
	private WirelessMapper wirelessMapper;

	@Autowired
	private GroupService groupService;

	@Override
	@Transactional
	@doLog(description = Tips.LogAddNetwork, key = { "#networkInput.network.name" })
	public RestResult add(NetworkInput networkInput, long userGroupId) {
		RestResult result = new RestResult();
		
		Network network = networkInput.getNetwork();
		Location location = networkInput.getLocation();
		if (network.getName().length() > 64) {
			result.setErrorCode(1);
			result.setErrorMsg(messageSourceUtil.getMessage(Tips.NetworkNameNotGreaterThan64Letters));
			return result;
		}
		if (location.getName().length() > 128) {
			result.setErrorCode(1);
			result.setErrorMsg(messageSourceUtil.getMessage(Tips.AddressNameNotGreaterThan128Letters));
			return result;
		}
		List<Long> deviceIds = networkInput.getDeviceIds();
		List<Device> devices = null;
		System.out.println("deviceIds0: "+JSON.toJSONString(deviceIds));
		if (deviceIds != null && deviceIds.size() > 0) {
			devices = deviceMapper.queryDevicesByIds(deviceIds);
			if (devices != null) {
				if (!deviceService.hasRights(devices, userGroupId)) {
					result.setErrorCode(1);
					result.setErrorMsg(messageSourceUtil.getMessage(Tips.PermissionDenied));
					return result;
				}
			}
		}
		
		List<Long> wirelessIds = networkInput.getWirelessIds();
		List<Wireless> wirelesses = null;
		if (wirelessIds != null && wirelessIds.size() > 0) {
			wirelesses = wirelessMapper.queryByIds(wirelessIds);
			List<Map<String, Object>> vids = ssidMapper.checkVid(wirelessIds);
			if (vids != null) {
				for (int i = 0; i < vids.size(); i++) {
					Map<String, Object> vid = vids.get(i);
					if (vid.get("vid").toString().equals("0")) {
						continue;
					} else {
						if (Integer.parseInt(vid.get("total").toString()) > 1) {
							result.setErrorCode(1);
							result.setErrorMsg(messageSourceUtil.getMessage(Tips.NoSaveVlan));
							return result;
						}
					}
				}
			}
		}
		if (location != null) {
			locationMapper.save(location);
		}
		network.setLocationId(location.getId());
		Group parent = groupMapper.queryById(networkInput.getGroupId());
		network.setGroup(parent.getName());
		network.setGroupId(parent.getId());
		networkMapper.save(network);
		
		updateGroupNetwork(networkInput.getGroupId(), network.getId());
		
		System.out.println("deviceIds1: "+JSON.toJSONString(deviceIds));
		
		if (deviceIds != null && deviceIds.size() > 0) {
			deviceMapper.updateDevicesNetworkId(deviceIds, network.getId());
			for (Device device : devices) {
				device.setNetworkId(network.getId());
			}
		}
		
		if (wirelesses != null && wirelesses.size() > 0) {
			wirelessNetworkMapper.save(network.getId(), wirelessIds);
			if (devices != null && devices.size() > 0) {
				deviceService.updateDeviceWireless(devices, wirelesses);
			}
		} else {
			if (deviceIds != null && deviceIds.size() > 0) {
				deviceService.updateDeviceWireless(devices, null);
			}
		}
		result.setErrorMsg(messageSourceUtil.getMessage(Tips.OperationSucceed));
		return result;
	}

	public void updateGroupNetwork(long groupId, long networkId) {
		if (groupId == 0 || networkId == 0) {
			return;
		}
		List<Long> groupIds = groupService.queryDirectGroup(groupId);
		groupNetworkMapper.batchSave(groupIds, networkId);
	}

	@Override
	@Transactional
	@doLog(description = Tips.LogUpdateNetwork, key = { "#networkInput.network.name" })
	public RestResult update(NetworkInput networkInput, long userGroupId) {
		RestResult result = new RestResult();
		Network network = networkInput.getNetwork();
		Location location = networkInput.getLocation();
		if (network.getName().length() > 64) {
			result.setErrorCode(1);
			result.setErrorMsg(messageSourceUtil.getMessage(Tips.NetworkNameNotGreaterThan64Letters));
			return result;
		}
		if (location.getName().length() > 128) {
			result.setErrorCode(1);
			result.setErrorMsg(messageSourceUtil.getMessage(Tips.AddressNameNotGreaterThan128Letters));
			return result;
		}
		List<Long> deviceIds = networkInput.getDeviceIds();
		List<Device> devices = null;
		if (deviceIds != null && deviceIds.size() > 0) {
			devices = deviceMapper.queryDevicesByIds(deviceIds);
			if (devices != null) {
				if (!deviceService.hasRights(devices, userGroupId)) {
					result.setErrorCode(1);
					result.setErrorMsg(messageSourceUtil.getMessage(Tips.PermissionDenied));
					return result;
				}
			}
		}
		List<Long> wirelessIds = networkInput.getWirelessIds();
		List<Wireless> wirelesses = null;
		if (wirelessIds != null && wirelessIds.size() > 0) {
			wirelesses = wirelessMapper.queryByIds(wirelessIds);
			List<Map<String, Object>> vids = ssidMapper.checkVid(wirelessIds);
			if (vids != null) {
				for (int i = 0; i < vids.size(); i++) {
					Map<String, Object> vid = vids.get(i);
					if (vid.get("vid").toString().equals("0")) {
						continue;
					} else {
						if (Integer.parseInt(vid.get("total").toString()) > 1) {
							result.setErrorCode(1);
							result.setErrorMsg(messageSourceUtil.getMessage(Tips.NoSaveVlan));
							return result;
						}
					}
				}
			}
		}
		
		Group parent = groupMapper.queryById(networkInput.getGroupId());
		network.setGroup(parent.getName());
		network.setGroupId(parent.getId());
		networkMapper.update(network);
		
		groupNetworkMapper.deleteByNetworkIds(new ArrayList<Long>() {{add(network.getId());}});
		updateGroupNetwork(networkInput.getGroupId(),network.getId());
		
		//update
		if (location != null) {
			locationMapper.update(location);
		}
		
		if (deviceIds != null && deviceIds.size() > 0) {
			deviceMapper.deleteDevicesNetworkId(network.getId());
			deviceMapper.updateDevicesNetworkId(deviceIds, network.getId());
			for (Device device : devices) {
				device.setNetworkId(network.getId());
			}
		} else {
			deviceMapper.deleteDevicesNetworkId(network.getId());
		}
		
		if (wirelesses != null && wirelesses.size() > 0) {
			wirelessNetworkMapper.deleteByNetworkIds(new ArrayList<Long>() {{add(network.getId());}});
			wirelessNetworkMapper.save(network.getId(), wirelessIds);
			if (devices != null && devices.size() > 0) {
				deviceService.updateDeviceWireless(devices, wirelesses);
			}
		} else {
			wirelessNetworkMapper.deleteByNetworkIds(new ArrayList<Long>() {{add(network.getId());}});
			if (deviceIds != null && deviceIds.size() > 0) {
				deviceService.updateDeviceWireless(devices, null);
			}
		}
		
		result.setErrorCode(0);
		result.setErrorMsg(messageSourceUtil.getMessage(Tips.OperationSucceed));
		return result;
	}

	@Override
	@Transactional
	@doLog(description = Tips.LogDeleteNetwork, key = { "" })
	public RestResult delete(List<Long> networkIds) {
		RestResult result = new RestResult();
		int count = deviceMapper.queryIfHasReference(networkIds);
		if (count > 0) {
			result.setErrorCode(1);
			result.setErrorMsg(messageSourceUtil.getMessage(Tips.NetworkNoDelete1));
			return result;
		}
		List<Network> networks = networkMapper.queryByIds(networkIds);
		List<Long> groupIds = new ArrayList<>();
		for (Network network : networks) {
			groupIds.add(network.getGroupId());
		}
		networkMapper.delete(networkIds);
		wirelessNetworkMapper.deleteByNetworkIds(networkIds);
		groupNetworkMapper.deleteByNetworkIds(networkIds);
		result.setErrorMsg(messageSourceUtil.getMessage(Tips.OperationSucceed));
		return result;
	}

	@Override
	public TableOutput<NetworkInfo> queryList(TableInput input, long userGroupId) {
		Map<String, Object> conditions = new HashMap<>();
		List<Long> networkIds = new ArrayList<>();
		boolean flag = false;
		if (input.getSearch() != null && input.getSearch().size() > 0) {
			Iterator<SearchParameter> iterator = input.getSearch().iterator();
			while (iterator.hasNext()) {
				SearchParameter search = iterator.next();
				if ("network_id".equals(search.getColumn())) {
					// 如果有以参数中的network来查询设备，如果没有则以组下的所有局点来查询
					networkIds.add(-Long.parseLong(search.getValue()));
					flag = true;
					iterator.remove();
					break;
				}
				if ("group_id".equals(search.getColumn())) {
					Long groupId = Long.parseLong(search.getValue());
					List<Long> ids = groupNetworkMapper.queryByGroupId(groupId);
					networkIds.addAll(ids);
					flag = true;
					iterator.remove();
					break;
				}
			}
		}
		if (!flag) {
			List<Long> ids = groupNetworkMapper.queryByGroupId(userGroupId);
			networkIds.addAll(ids);
		}
		conditions.put("networkIds", networkIds);
		conditions.put("searchs", input.getSearch());
		if (input.getOrder() != null) {
			conditions.put("orderColumn", input.getOrder().getColumn());
			conditions.put("orderDirection", input.getOrder().getDir());
		}
		conditions.put("start", input.getStart());
		conditions.put("rows", input.getRows());
		int total = 0;
		List<Network> networks = new ArrayList<>();
		if (networkIds.size() >0) {
			networks = networkMapper.queryByCondition(conditions);
			total=networkMapper.queryCountByCondition(conditions);
		}
		TableOutput<NetworkInfo> output = new TableOutput<>();
		output.setTotal(total);
		output.setRows(input.getRows());
		output.setStart(input.getStart());
		List<NetworkInfo> infos = new ArrayList<>();
		for (Network network : networks) {
			NetworkInfo info = new NetworkInfo();
			info.convert(network);
			String manager = "";
			info.setManager(manager);
			int count = deviceMapper.queryCountByNetworkId(network.getId());
			info.setDeviceCount(count);
			infos.add(info);
		}
		Collections.sort(infos, new Comparator<NetworkInfo>() {
			public int compare(NetworkInfo o1, NetworkInfo o2) {
				return o1.getCreatetime().compareTo(o2.getCreatetime());
			}
		});
		output.setList(infos);
		return output;
	}

	@Override
	public boolean hasRight(long userGroupId, List<Long> networkIds) {
		if (networkIds.size() < 0) {
			return false;
		}
		List<Long> result = groupNetworkMapper.queryByGroupId(userGroupId);
		for (long networkId : networkIds) {
			if (!result.contains(networkId)) {
				return false;
			}
		}
		return true;
	}

	@Override
	public List<Network> queryByIds(List<Long> networkIds) {
		if (networkIds == null || networkIds.size() == 0) {
			return new ArrayList<>();
		}
		return networkMapper.queryByIds(networkIds);
	}

	@Override
	@doLog(description = Tips.LogUpdateNetwork, key = { "#temp.name" })
	public RestResult updateName(Network temp) {
		RestResult result=new RestResult();
		Network network = networkMapper.queryById(temp.getId());
		network.setName(temp.getName());
		networkMapper.update(network);
		return result;
	}
	
	@Override
	public Location queryLocation(long locationId) {
		Location location = locationMapper.queryLocation(locationId);
		return location;
	}
	
}
